<template>
    <a-cascader
        v-if="editorStyle == 'cascader'"
        :class="[
                'app-editor-container',
                'app-dropdown-list',
                `app-dropdown-list-${name}`,
            ]"
        :value="curValue"
        :disabled="disabled || readonly"
        :multiple="multiple"
        :options="items"
        :fieldNames="{children:'children', label:'text', value: 'value' }"
        :placeholder="placeholder"
        showCheckedStrategy="SHOW_CHILD"
        @blur="onBlur"
        @focus="onFocus"
        @change="onChange"
    ></a-cascader>
    <a-tree-select
        v-else-if="hasChildren"
        :class="[
            'app-editor-container',
            'app-dropdown-list',
            `app-dropdown-list-${name}`,
        ]"
        :value="curValue"
        :placeholder="placeholder"
        :allowClear="clearable"
        :tree-data="items"
        :disabled="disabled || readonly"
        :tree-checkable="multiple"
        @blur="onBlur"
        @focus="onFocus"
        @change="onChange"
        :fieldNames="{children:'children', label:'text', value: 'value' }"
    >
    </a-tree-select>
    <a-select
        v-else
        :class="[
            'app-editor-container',
            'app-dropdown-list',
            `app-dropdown-list-${name}`,
        ]"
        :value="curValue"
        :options="items"
        :mode="multiple ? 'multiple' : undefined"
        :disabled="disabled || readonly"
        :placeholder="placeholder"
        :allowClear="clearable"
        :showSearch="filterable"
        :filterOption="filterable && filterOption"
        @blur="onBlur"
        @focus="onFocus"
        @change="onChange"
    >
    </a-select>
</template>
<script setup lang="ts">
import { onBeforeMount, Ref, ref } from 'vue';
import { dropdownListProps } from './dropdown-list';
import { IParam, IEvent, ICodeListItem, deepCopy } from '@/core';
import { typeOf } from '@/core';
import { handleEditorNavParams, useEditorTypeParams } from '@/hooks/use-editor';
interface EditorEmit {
	(name: 'component-action', value: IEvent<string>): void;
}
const props = defineProps(dropdownListProps);
const emit = defineEmits<EditorEmit>();
// 类型校验
const { validateConfig } = useEditorTypeParams();
validateConfig();
const { navContext, navViewParam } = handleEditorNavParams(props);
const hasChildren = ref(false);
let curValue: Ref<any> = computed(() => {
	if(props.editorStyle == 'cascader'){
		try {
			if(props.value && typeOf(props.value) == 'string'){
				return JSON.parse(props.value as string);
			}else{
				return null;
			}
		}catch{
			return null;
		}
	}
	if (props.multiple) {
		return props.value
			? (props.value as string).split(props.valueSeparator)
			: [];
	} else {
		let value = props.value;
		if (!value && value !== 0) {
			return value;
		}
		const type = typeOf(value);
		if (type == props.valueType) {
			return value;
		} else {
			if (type === 'number') {
				value = value.toString();
			} else if ((value as String).indexOf('.') == -1) {
				value = parseInt(value as string);
			} else {
				value = parseFloat(value as string);
			}
			return value;
		}
	}
});
let items: Ref<IParam[]> = ref([]);

const onChange = (select: any, option: any) => {
	if(props.editorStyle == 'cascader'){
		emit('component-action', {
			name: props.name as string,
			action: 'valueChange',
			data: JSON.stringify(select),
		});
		return;
	}
	const value =
	typeOf(select) == 'array' ? select.join(props.valueSeparator) : select;
	emit('component-action', {
		name: props.name as string,
		action: 'valueChange',
		data: value,
	});
};
// 内置筛选
const filterOption = (inputValue:string, option:any)=>{
	return option.label.indexOf(inputValue) != -1;
}
const onBlur = () => {
	emit('component-action', {
		name: `${props.name}`,
		action: 'editorBlur',
		data: curValue.value,
	});
};
const onFocus = () => {
	emit('component-action', {
		name: `${props.name}`,
		action: 'editorFocus',
		data: curValue.value,
	});
};

onBeforeMount(() => {
    loadData();
});

const formatCodeList = (items: Array<any>) => {
	let matching = false;
	let result: Array<any> = [];
	try {
		items.forEach((item: any) => {
			const type = typeOf(item.value);
			if (type != props.valueType) {
				matching = true;
				if (type === 'number') {
					item.value = item.value.toString();
				} else {
					if (type == 'null') {
						props.valueType == 'number' ? (item.value = 0) : (item.value = '');
					} else if (item.value.indexOf('.') == -1) {
						item.value = parseInt(item.value);
					} else {
						item.value = parseFloat(item.value);
					}
				}
			}
			result.push(item);
		});
		if (matching) {
			console.warn(
				App.ts(
					'common.generic.codelistcast',
					'代码表值类型和属性类型不匹配，自动强制转换'
				)
			);
		}
		return result;
	} catch (error) {
		console.warn(
			App.ts(
				'common.generic.codelistwarn',
				'代码表值类型和属性类型不匹配，自动强制转换异常，请修正代码表值类型和属性类型匹配'
			)
		);
		return [];
	}
};

const loadData = async () => {
	if (props.codeListTag && props.codeListType) {
		await App.getAppCodeListHelper()
			.getCodeListItems(props.codeListTag, navContext, navViewParam)
			.then((codeListResult: any) => {
				if (codeListResult.ok) {
					const result = formatCodeList(codeListResult.data);
					handleLevelCodeList(result)
				}
			})
			.catch((error: any) => {
				console.warn(App.ts('common.generic.codenotexist', '代码表不存在'));
			});
	}
};

// 格式化数据
const handleLevelCodeList = (result:any[])=>{
	const setChildCodeItems = (pValue:string,result:Array<any>,codeItem:any)=>{
        result.forEach((item:any) =>{
            if(item.pvalue == pValue){
                let valueField:string = item.value;
                setChildCodeItems(valueField,result,item);
                if(!codeItem.children){
                    codeItem.children = [];
                }
                codeItem.children.push(item);
            }
        })
    }
	const handleDefault = ()=>{
		result.forEach((item: ICodeListItem) => {
			items.value.push({ ...item, label: item.text });
		});
	}
    if(result && result.length > 0){
        hasChildren.value = result.some((item:any) =>{
            return item.pvalue;
        }) ? true : false;
        if(hasChildren.value){
            let list: Array<any> = [];
            result.forEach((item: any) => {
                const index = result.findIndex((_item: any) => item.pvalue == _item.value);
                if (index == -1) {
                    list.push(deepCopy(item));
                }
            })
            list.forEach((item:any) => {
                setChildCodeItems(item.value, result, item);
            })
            items.value = list;
        }else{
            handleDefault();
        }
    }
}
</script>
